//
//  HttpService.swift
//  swiftProject
//
//  Created by ZhangSai on 2021/5/24.
//

import UIKit
import Alamofire
import SwiftyJSON
import Toast_Swift
import HandyJSON

class HttpService: NSObject {
    
    var refreshTokenTag:Bool = false
    
    
    static let instance : HttpService = HttpService()
    class func sharedHttpService() -> HttpService {
        return instance
    }
    
    
//    var headers:HTTPHeaders!

    func getHTTPHeaders(action:String) -> HTTPHeaders {
        var headers:HTTPHeaders
        let str = UserDefaults.standard.string(forKey:LanguageHeader.MySystemLanguage)
        var languageStr:String = "us";
        if (str == LanguageHeader.ChinaLanguage) {
            languageStr = "cn"
        } else if (str == LanguageHeader.BurmaLanguage) {
            languageStr = "bu"
        } else {
            languageStr = "us"
        }
        
        let touten:String = UserDefaults.standard.string(forKey: ActionHeader.UserDefault_Token) ?? ""
        let tokenHead:String = UserDefaults.standard.string(forKey:ActionHeader.UserDefault_TokenHead) ?? ""
        
        if !self.isContainToken(action: action) {
            headers = ["Content-Typ":"application/json","Accept-Language":languageStr,"Authorization":tokenHead + touten]
        } else {
            headers = ["Content-Typ":"application/json","Accept-Language":languageStr]
        }
        return headers;
    }
    
    func isContainToken(action:String) -> Bool {
        if (action == ActionHeader.Action_Login_UserAuthCode ||
                action == ActionHeader.Action_Login_ResetPasswork ||
                action == ActionHeader.Action_Login_ByAuthCode ||
                action == ActionHeader.Action_Login_ByThird ||
                action == ActionHeader.Action_Login_refreshToken ||
                action == ActionHeader.Action_Login_phoneBind ||
                action == ActionHeader.Action_Login_Password ||
                action == ActionHeader.Action_Config_getCountry ||
                action == ActionHeader.Action_Config_verifyArea ||
                action == ActionHeader.Action_Config_calculateFreight ||
                action == ActionHeader.Action_Config_getMyanmarArea) {
            return true;
        }
        return false;
    }
    
    func isConnectNetWork() -> Bool {
        var isExistenceNetwork = true
        let r = Reachability.init(hostname: "www.baidu.com")
        switch r?.currentReachabilityStatus() {
        case .NotReachable:
            isExistenceNetwork = false
            break
        case .ReachableViaWWAN:
            isExistenceNetwork = true;
            break
        case .ReachableViaWiFi:
            isExistenceNetwork = true;
            break
        default: break
        }
        return isExistenceNetwork
    }
    
    func refreshTokenCalculate(calculate:Bool,finishedCallback:@escaping (_ state:Bool) ->()) {
        let tokenexpiryDuratio = WLUserModel.tokenexpiryDuratio()//token 有效时间
        let validTimer:Double = Double(tokenexpiryDuratio) ?? 0
        let resTimer:Double = Double(WLUserModel.tokenexResTimer()) ?? 0//上次请求token时间
        let currentTimes:Double = Double(TimerTool.getCurrentTimes()) ?? 0//当前时间
        //距离上次请求token时间差 当前时间-上次请求token时间
        let newTime = currentTimes - resTimer + 250000
        if newTime > validTimer || !calculate {
            let dicData = ["refreshToken":WLUserModel.tokenrefresh(),"userId":WLUserModel.getEMPId()]
            if !self.refreshTokenTag {
                self.refreshTokenTag = true
                self.httpRequest(action: ActionHeader.Action_Login_refreshToken, isRefreshToken: false, param: dicData) { (json, state, error) in
                    self.refreshTokenTag = false
                    if state {
                        WLUserModel.saveUser(jsonDic: json)
                        finishedCallback(true)
                    } else {
                        finishedCallback(false)
                    }
                }
            }
        } else {
            finishedCallback(true)
        }
    }
    
    func httpRequest(action:String,isRefreshToken:Bool,param:[String:Any],finishedCallback:@escaping (_ resultjson: JSON, _ state:Bool,_ message:String) ->()) {
        if !self.isConnectNetWork() {
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            finishedCallback("",false,ZslanguageTool.sharedLanguageTool().getIanguageWithKey(key: LanguageHeader.network_connection_failed))
            return
        }
        if isRefreshToken {
            self.refreshTokenCalculate(calculate: true) { (state) in
                if state {
                    self.httpRequest(action: action, isRefreshToken: false, param: param) { (Json, state, error) in
                        finishedCallback(Json,state,error)
                    }
                } else {
                    finishedCallback("",false,"与服务器链接失败")
                }
            }
            return
        }
        let infoDictionary:Dictionary = Bundle.main.infoDictionary ?? [:]
        let appBundleIdentifier:String = infoDictionary["CFBundleVersion"] as! String
        var ReqDic:[String: Any] = [String: Any]()

        let userID = WLUserModel.getEMPId()
        ReqDic["userID"] = userID
        ReqDic["data"] = param
        ReqDic["appVersion"] = "v"+appBundleIdentifier
        ReqDic["action"] = (action as NSString).replacingOccurrences(of: "/", with: ".") as String
        ReqDic["reqTime"] = TimerTool.getCurrentTimes()

        
        AF.request(Constants.URL_PRO_ROOT + action, method:.post, parameters:ReqDic , encoding: JSONEncoding.default, headers: self.getHTTPHeaders(action: action)).responseJSON { responseJson in

            let responseString = JSON(responseJson.value ?? "")
            let code = responseString["code"].int
            let message = responseString["message"].string

            switch responseJson.result {
            case .success(_/*let resultString*/):
                if ((code == 102 && action == ActionHeader.Action_Login_refreshToken) || code == 401 && action != ActionHeader.Action_Login_refreshToken) {
                    let VC = HttpService.sharedHttpService().currentViewController()
                    if !(VC is HostLoginController) {
                        let windows = UIApplication.shared.windows.first
                        windows?.hideAllToasts()
                        windows?.makeToast(message)
                        self.quitLogin()
                        return
                    }
                }
                let resTime_verify = responseString["resTime"].double ?? 0
                let now:TimeInterval = NSDate.init().timeIntervalSince1970
                let difference_timer:TimeInterval = now * 1000 - resTime_verify
                UserDefaults.standard.setValue(difference_timer, forKey: ActionHeader.UserDefault_TimerDifference)

                if code == 200 || code == 106 || code == 302 {
                    finishedCallback(responseString,true,"")
                } else {
                    finishedCallback("",false,message ?? "")
                }
                break
                
            case .failure(_):
                if ((code == 401 && action != ActionHeader.Action_Login_refreshToken) || (code == 201 && action == ActionHeader.Action_Login_refreshToken)) {
                    let VC = HttpService.sharedHttpService().currentViewController()
                    if !(VC is HostLoginController) {
                        let windows = UIApplication.shared.windows.first
                        windows?.hideAllToasts()
                        windows?.makeToast(message)
                        self.quitLogin()
                        return
                    }
                } else {
                    finishedCallback("",false,message ?? "")
                }
                break
            }
        }
        
    }
    
    func quitLogin()  {
        let defaults:UserDefaults = UserDefaults.standard
        defaults.setValue("", forKey: ActionHeader.UserDefault_Token)
        defaults.setValue("", forKey: ActionHeader.UserDefault_TokenHead)
        defaults.setValue("", forKey: ActionHeader.UserDefault_Tokenrefresh)
        defaults.setValue("", forKey: ActionHeader.UserDefault_TokenexpiryDuration)
        
        defaults.setValue("", forKey: ActionHeader.UserDefault_NiceName)
        defaults.setValue("", forKey: ActionHeader.UserDefault_AvatarPath)
        defaults.setValue("", forKey: ActionHeader.UserDefault_Gender)
        defaults.setValue("", forKey: ActionHeader.UserDefault_UserType)
        defaults.setValue("", forKey: ActionHeader.UserDefault_UserId)
        defaults.setValue("", forKey: ActionHeader.UserDefault_UserName)
        defaults.setValue("", forKey: ActionHeader.UserDefault_Phone)

        defaults.setValue("", forKey: ActionHeader.UserDefault_Email)
        defaults.setValue("", forKey: ActionHeader.UserDefault_PhoneCode)
        defaults.setValue("", forKey: ActionHeader.UserDefault_RoleType)

        let optionModel:OptionModel = OptionModel.init(key: ActionHeader.WLAutoLogin)
        optionModel.value = "0";
        CacheTool.cacheTool.addOptiontWith(item: optionModel)
        
        UIApplication.shared.windows.first?.rootViewController = ZsNavigationController.init(rootViewController: HostLoginController.init())
    }
    
    //获取手机地区
    func getSmsCountrySuccess(finishedCallback:@escaping (_ resultDic:Bool,_ countryModes:WLCountryCode) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_getCountry, isRefreshToken: false, param: [:]) { (swiftyJsonVar, state, messageStr) in
            if state == true {
                Constants.window?.hideAllToasts()
                let model:Array<WLCountryCode> = JSONDeserializer<WLCountryCode>.deserializeModelArrayFrom(json: swiftyJsonVar["data"].description) as! Array<WLCountryCode>
                CacheTool.cacheTool.addCountryCodes(countryModes: model)
                finishedCallback(true,model.first!)
            } else {
                let model:Array<WLCountryCode> = CacheTool.cacheTool.searchCountryCodes()
                if model.count > 0 {
                    finishedCallback(true,model.first!)
                } else {
                    finishedCallback(false,WLCountryCode())
                }
            }
        }
    }
    
    //获取网店城市
    func getMyanmarAreaSuccess(finishedCallback:@escaping (_ resultState:Bool) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_getMyanmarArea, isRefreshToken: false, param: ["id":"0"]) { (swiftyJsonVar, state, messageStr) in
            Constants.window?.hideAllToasts()
            if state == true {
                let model:Array<WLAreaModel> = JSONDeserializer<WLAreaModel>.deserializeModelArrayFrom(json: swiftyJsonVar["data"].description) as! Array<WLAreaModel>
                CacheTool.cacheTool.addAreaList(areaModes: model)
                finishedCallback(true)
            } else {
                finishedCallback(false)
            }
        }
    }
    
    //获取联系电话
    func getPhoneListSuccess(finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_getPhoneList, isRefreshToken: false, param: [:]) { (swiftyJsonVar, state, messageStr) in
            Constants.window?.hideAllToasts()
            if state {
                finishedCallback(swiftyJsonVar["data"],state,messageStr)
            } else {
                finishedCallback("",state,messageStr)
            }
        }
    }
    
    func getGoodsTypeSuccess(finishedCallback:@escaping (_ state:Bool) ->()) {
        CacheTool.cacheTool.removeGoodsType()
        self.httpRequest(action: ActionHeader.Action_Config_getGoodsType, isRefreshToken: false, param: [:]) { (json, state, error) in
            Constants.window?.hideToastActivity()
            Constants.window?.hideAllToasts()
            if state {
                if json["date"].array?.count ?? 0 > 0 {
                    CacheTool.cacheTool.addGoodsType(goodsType: json["date"].array!)
                }
            }
            finishedCallback(state)
        }
    }
    
    func getlogisticsStatisticsSuccess(finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        let dic = ["userId":WLUserModel.getEMPId(),"userType":WLUserModel.getUserType()]
        self.httpRequest(action: ActionHeader.Action_Search_logisticsStatistics, isRefreshToken: true, param: dic) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            finishedCallback(json,state,error)
        }
    }
    
    func getSyncServerTimeSuccess(finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_getsyncServerTime, isRefreshToken: false, param: [:]) { (josn, state, error) in
            finishedCallback(josn,state,error)
        }
    }
    
    func loginWithPassWord(dicData:[String:Any],finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->())  {
        var dicData = dicData
        dicData["registrationId"] = ""
        self.httpRequest(action: ActionHeader.Action_Login_Password, isRefreshToken: false, param: dicData) { (swiftyJsonVar, state, messageStr) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            if state {
                finishedCallback(swiftyJsonVar,state,messageStr)
            } else {
                finishedCallback("",state,messageStr)
            }
        }
    }
    
    func getUserInfoMsg(finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_User_info, isRefreshToken: true, param: [:]) { (JSON, state, erroe) in
            Constants.window?.hideToastActivity()
            Constants.window?.hideAllToasts()
            finishedCallback(JSON["data"],state,erroe)
        }
    }
    
    func getScreenArea(mutDic:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->())  {
    }
    
    func getOrderList(mutDic:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        var tempDic = mutDic
        tempDic["pageSize"] = (20)
        tempDic["companyCode"] = WLUserModel.getCompanyCode()
        tempDic["staffCode"] = WLUserModel.getStaffCode()
        tempDic["userId"] = WLUserModel.getEMPId()
        self.httpRequest(action: ActionHeader.Action_Order_getOrderList, isRefreshToken: true, param: tempDic, finishedCallback: { (json, state, message) in
            let aryData:Array = json["data"]["orderStatusCounts"].array ?? Array()
            if aryData.count > 0 {
                let srt:String = mutDic["orderStatus"] as! String
                if srt == "-9" {
                    NotificationCenter.default.post(name: Notification.Name(ActionHeader.Order_titleCount), object: self, userInfo: ["orderStatusCounts":aryData])
                }
             }
            finishedCallback(json,state,message)
        })
    }
    
    func getScreenCity(mutDic:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        var tempDic = mutDic
        tempDic["userType"] = WLUserModel.getUserType()
        tempDic["companyCode"] = WLUserModel.getEMPId()
        tempDic["staffCode"] = WLUserModel.getCompanyCode()
        tempDic["userId"] = WLUserModel.getStaffCode()
        self.httpRequest(action: ActionHeader.Action_Order_screenCity, isRefreshToken: true, param: mutDic) { (json, state, message) in
            finishedCallback(json,state,message)
        }
    }
    
    func cancelOrder(mailSn:String,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        let dic = ["userId":WLUserModel.getEMPId(),"userType":WLUserModel.getUserType(),"companyCode":WLUserModel.getCompanyCode(),"mailSn":mailSn]
        self.httpRequest(action: ActionHeader.Action_OrderOperate_cancel, isRefreshToken: true, param: dic) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    
    func deleteOrder(mailSn:String,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        let dic = ["userId":WLUserModel.getEMPId(),"userType":WLUserModel.getUserType(),"mailSn":mailSn]
        self.httpRequest(action: ActionHeader.Action_OrderOperate_delete, isRefreshToken: true, param: dic) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    
    func getrecAndSendSupport(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_recAndSendSupport, isRefreshToken: true, param: dicData) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    func getInsuredPlanSuccess(finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_getInsuredPlan, isRefreshToken: false, param: [:]) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    
    func getCalculateInsuredFreight(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_calculateInsuredFreight, isRefreshToken: false, param: dicData) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            finishedCallback(json,state,error)
        }
    }
    func getFreightValue(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_calculateFreight, isRefreshToken: false, param: dicData) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    func getCalculateWareFreight(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_calculateWareFreight, isRefreshToken: false, param: dicData) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    func getCollectionScopeSuccess(finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        self.httpRequest(action: ActionHeader.Action_Config_getCollectionScope, isRefreshToken: false, param: [:]) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    
    func generateOrder(orderInfo:OrderListModel,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        //var dic = ["":,]
        self.httpRequest(action: ActionHeader.Action_Order_generateOrder, isRefreshToken: true, param: [:]) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    func modifyOrDeleteOrder(orderInfo:OrderListModel,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        //var dic = ["":,]
        self.httpRequest(action: ActionHeader.Action_Order_modify, isRefreshToken: true, param: [:]) { (json, state, error) in
            finishedCallback(json,state,error)
        }
    }
    
    func getUserAddressListSuccess(finishedCallback:@escaping (_ addressModelList: Array<AddressModel>, _ state:Bool,_ message:String) ->()) {
        let dicData = ["userId":WLUserModel.getEMPId()]
        self.httpRequest(action: ActionHeader.Action_Address_List, isRefreshToken: true, param: dicData) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            if state {
                let model:Array<AddressModel> = JSONDeserializer<AddressModel>.deserializeModelArrayFrom(json: json["data"].description) as! Array<AddressModel>
                CacheTool.cacheTool.insterAddressList(addressList: model)
                finishedCallback(model,state,error)
            } else {
                finishedCallback(Array(),state,error)
            }
        }
    }
    func deleteAddress(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        httpRequest(action: ActionHeader.Action_Address_delete, isRefreshToken: true, param: dicData) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            finishedCallback(json,state,error)
        }
    }
    func setDefaultAddress(ID:String,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        let dic = ["userId":WLUserModel.getEMPId(),"id":ID]
        httpRequest(action: ActionHeader.Action_Address_Default, isRefreshToken: true, param: dic) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            if state {
                self.getUserAddressListSuccess { (addressModelList, state, error) in
                    if state {
                        finishedCallback(json,state,error)
                    } else {
                        finishedCallback(json,state,error)
                    }
                }
            } else {
                finishedCallback(json,state,error)
            }
            
        }
    }
    func cancelDefaultAddress(ID:String,finishedCallback:@escaping (_ resultData: JSON, _ state:Bool,_ message:String) ->()) {
        let dic = ["userId":WLUserModel.getEMPId(),"id":ID]
        httpRequest(action: ActionHeader.Action_Address_CancelDefault, isRefreshToken: true, param: dic) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            if state {
                self.getUserAddressListSuccess { (addressModelList, state, error) in
                    if state {
                        finishedCallback(json,state,error)
                    } else {
                        finishedCallback(json,state,error)
                    }
                }
            } else {
                finishedCallback(json,state,error)
            }
            
        }
    }
    func getDefaultAddressSuccess(finishedCallback:@escaping (_ model: AddressModel, _ state:Bool,_ message:String) ->()) {
        let dic = ["userId":WLUserModel.getEMPId()]
        httpRequest(action: ActionHeader.Action_Address_getDefault, isRefreshToken: true, param: dic) { (json, state, error) in
            Constants.window?.hideAllToasts()
            Constants.window?.hideToastActivity()
            if json["data"].dictionary?.count ?? 0 > 0 {
                let addressModel = AddressModel.deserialize(from: json["data"].dictionary)
                finishedCallback(addressModel!,state,error)
            } else {
                finishedCallback(AddressModel(),false,error)
            }
        }
    }
    
    func modifyAddress(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ success: AddressModel, _ state:Bool,_ message:String) ->()) {
        httpRequest(action: ActionHeader.Action_Address_modify, isRefreshToken: true, param: dicData) { (json, state, error) in
            if state {
                let model:AddressModel = AddressModel.deserialize(from: json["data"].dictionary)!
                CacheTool.cacheTool.insterAddressList(addressList: [model])
                Constants.window?.hideToastActivity()
                finishedCallback(model,false,error)
            } else {
                finishedCallback(AddressModel(),false,error)
            }
        }
    }
    func addAddress(dicData:Dictionary<String, Any>,finishedCallback:@escaping (_ success: AddressModel, _ state:Bool,_ message:String) ->()) {
        httpRequest(action: ActionHeader.Action_Address_add, isRefreshToken: true, param: dicData) { (json, state, error) in
            if state {
                let model:AddressModel = AddressModel.deserialize(from: json["data"].dictionary)!
                CacheTool.cacheTool.insterAddressList(addressList: [model])
                Constants.window?.hideToastActivity()
                finishedCallback(model,false,error)
            } else {
                finishedCallback(AddressModel(),false,error)
            }
        }
    }
    
}
